package com.NetSDKDemo;

import com.demo.impl.Websocket;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import static com.NetSDKDemo.ClientDemo.hCNetSDK;

/**
 * 视频取流预览，下载，抓图mok
 *
 * @create 2022-03-30-9:48
 */
public class VideoDemo {
    static fPlayEScallback fPlayescallback; // 裸码流回调函数
    static FileOutputStream outputStream;
    static IntByReference m_lPort = new IntByReference(-1);

    /**
     * 获取实时裸码流回调数据
     *
     * @param userID     登录句柄
     * @param iChannelNo 通道号参数
     */
    public static int getESRealStreamData(int userID, int iChannelNo) {
        if (userID == -1) {
            System.out.println("请先注册");
            return -1;
        }
        HCNetSDK.NET_DVR_PREVIEWINFO previewInfo = new HCNetSDK.NET_DVR_PREVIEWINFO();
        previewInfo.read();
        previewInfo.hPlayWnd = null;  // 窗口句柄，从回调取流不显示一般设置为空
        previewInfo.lChannel = iChannelNo;  // 通道号
        previewInfo.dwStreamType = 0; // 0-主码流，1-子码流，2-三码流，3-虚拟码流，以此类推
        previewInfo.dwLinkMode = 1; // 连接方式：0- TCP方式，1- UDP方式，2- 多播方式，3- RTP方式，4- RTP/RTSP，5- RTP/HTTP，6- HRUDP（可靠传输） ，7- RTSP/HTTPS，8- NPQ
        previewInfo.bBlocked = 1;  // 0- 非阻塞取流，1- 阻塞取流
        previewInfo.byProtoType = 0; // 应用层取流协议：0- 私有协议，1- RTSP协议
        previewInfo.write();
        // 开启预览
        int Handle = hCNetSDK.NET_DVR_RealPlay_V40(userID, previewInfo, null, null);
        if (Handle == -1) {
            int iErr = hCNetSDK.NET_DVR_GetLastError();
            System.err.println("取流失败" + iErr);
            return -1;
        }
        System.out.println("取流成功");

        // 设置裸码流回调函数
        if (fPlayescallback == null) {
            fPlayescallback = new fPlayEScallback();
        }
        if (!hCNetSDK.NET_DVR_SetESRealPlayCallBack(Handle, fPlayescallback, null)) {
            System.err.println("设置裸码流回调失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
        }

        /*

        Boolean bStopSaveVideo = hCNetSDK.NET_DVR_StopSaveRealData(lPlay);
        if (bStopSaveVideo == false) {
            int iErr = hCNetSDK.NET_DVR_GetLastError();
            System.out.println("NET_DVR_StopSaveRealData failed" + iErr);
            return;
        }
            System.out.println("NET_DVR_StopSaveRealData suss");


        if (lPlay>=0) {
            if (hCNetSDK.NET_DVR_StopRealPlay(lPlay))
            {
                System.out.println("停止预览成功");
                return;
            }
        }*/
        return Handle;
    }

    static class fPlayEScallback implements HCNetSDK.FPlayESCallBack {
        private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        private boolean start = false;

        public void invoke(int lPreviewHandle, HCNetSDK.NET_DVR_PACKET_INFO_EX pstruPackInfo, Pointer pUser) {
            pstruPackInfo.read();
            // 保存I帧和P帧数据
            // 从第一帧 I 帧开始解析
            if (pstruPackInfo.dwPacketType == 1) {
                start = true;
            }
            if (!start) {
                return;
            }
            if (pstruPackInfo.dwPacketType == 1 || pstruPackInfo.dwPacketType == 3) {
                // 如果是 I 帧，则将上一帧 I 帧到当前 I 帧的数据发送给 Websocket 解析
                if (pstruPackInfo.dwPacketType == 1) {
                    byte[] byteArray = outputStream.toByteArray();
                    outputStream.reset();
                    if (byteArray.length > 0) {
                        // 通过websocket发送
                        long start = System.currentTimeMillis();
                        Websocket.sendBuffer(byteArray);
                        System.out.println("cost: "+(System.currentTimeMillis() - start));
                    }
                }

                // System.out.println("dwPacketType：" + pstruPackInfo.dwPacketType
                //         + "：wWidth:" + pstruPackInfo.wWidth
                //         + "：wHeight:" + pstruPackInfo.wHeight
                //         + "：包长度：" + pstruPackInfo.dwPacketSize
                //         + "：帧号：" + pstruPackInfo.dwFrameNum);
                ByteBuffer buffers = pstruPackInfo.pPacketBuffer.getByteBuffer(0, pstruPackInfo.dwPacketSize);
                byte[] bytes = new byte[pstruPackInfo.dwPacketSize];
                buffers.rewind();
                buffers.get(bytes);
                try {
                    outputStream.write(bytes);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
